//
// AtomicCounter.h
//


#ifndef _AtomicCounter_H
#define _AtomicCounter_H


#if defined (_MSC_VER)
#include <windows.h>

#else	//linux
#include <pthread.h>
#endif


/* This class implements a simple counter, which
 provides atomic operations that are safe to
 use in a multithreaded environment.
*/
class AtomicCounter
{
public:
	typedef int ValueType; /// The underlying integer type.
	
	AtomicCounter(): _counter(0) {}
		
	explicit AtomicCounter(ValueType initialValue): _counter(initialValue) {}
	
	AtomicCounter(const AtomicCounter& counter): _counter(counter.value()) {}
	
	~AtomicCounter() {}

	AtomicCounter& operator = (const AtomicCounter& counter);
		
	AtomicCounter& operator = (ValueType value);

	operator ValueType () const;
		
	ValueType value() const;
		
	ValueType operator ++ (); // prefix
		
	ValueType operator ++ (int); // postfix
		
	ValueType operator -- (); // prefix
		
	ValueType operator -- (int); // postfix
		
	bool operator ! () const;

private:
#if defined (_MSC_VER)
	typedef volatile LONG ImplType;
#elif defined(__linux__)
	typedef int ImplType;
#endif // POCO_OS

	ImplType _counter;
};


//
// inlines
//


#if defined (_MSC_VER)
//
// Windows
//

inline AtomicCounter& AtomicCounter::operator = (const AtomicCounter& counter)
{
	InterlockedExchange(&_counter, counter.value());
	return *this;
}

inline AtomicCounter& AtomicCounter::operator = (ValueType value)
{
	InterlockedExchange(&_counter, value);
	return *this;
}

inline AtomicCounter::operator AtomicCounter::ValueType () const
{
	return _counter;
}

	
inline AtomicCounter::ValueType AtomicCounter::value() const
{
	return _counter;
}


inline AtomicCounter::ValueType AtomicCounter::operator ++ () // prefix
{
	return InterlockedIncrement(&_counter);
}

	
inline AtomicCounter::ValueType AtomicCounter::operator ++ (int) // postfix
{
	ValueType result = InterlockedIncrement(&_counter);
	return --result;
}


inline AtomicCounter::ValueType AtomicCounter::operator -- () // prefix
{
	return InterlockedDecrement(&_counter);
}

	
inline AtomicCounter::ValueType AtomicCounter::operator -- (int) // postfix
{
	ValueType result = InterlockedDecrement(&_counter);
	return ++result;
}

	
inline bool AtomicCounter::operator ! () const
{
	return _counter == 0;
}

#elif defined(__linux__)
//
// GCC 4.1+ atomic builtins.
//
inline AtomicCounter& AtomicCounter::operator = (const AtomicCounter& counter)
{
	__sync_lock_test_and_set(&_counter, counter.value());
	return *this;
}


inline AtomicCounter& AtomicCounter::operator = (AtomicCounter::ValueType value)
{
	__sync_lock_test_and_set(&_counter, value);
	return *this;
}

inline AtomicCounter::operator AtomicCounter::ValueType () const
{
	return _counter;
}

	
inline AtomicCounter::ValueType AtomicCounter::value() const
{
	return _counter;
}


inline AtomicCounter::ValueType AtomicCounter::operator ++ () // prefix
{
	return __sync_add_and_fetch(&_counter, 1);
}

	
inline AtomicCounter::ValueType AtomicCounter::operator ++ (int) // postfix
{
	return __sync_fetch_and_add(&_counter, 1);
}


inline AtomicCounter::ValueType AtomicCounter::operator -- () // prefix
{
	return __sync_sub_and_fetch(&_counter, 1);
}

	
inline AtomicCounter::ValueType AtomicCounter::operator -- (int) // postfix
{
	return __sync_fetch_and_sub(&_counter, 1);
}

	
inline bool AtomicCounter::operator ! () const
{
	return _counter == 0;
}
#endif // POCO_OS



#endif // _AtomicCounter_H
